package server;

import config.MongoDB;
import sluentities.GrammarSlotEntity;
import sluentities.GrammarVariableEntity;
import gate.Factory;
import gate.FeatureMap;
import gate.ProcessingResource;
import gate.creole.SerialAnalyserController;
import gate.creole.gazetteer.AbstractGazetteer;
import gate.creole.gazetteer.Lookup;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.query.Query;

import java.util.*;

/**
 * Created by Zhao on 2017/04/16.
 */
public class DefaultFunction {

    private List<AbstractGazetteer> listGaz = new ArrayList<>();

    private Map<String ,Map<String,String>> assignFunc = new HashMap<>();
    private Map<String,String> valType = new HashMap<>();
    private static Datastore mongoDatastore;

    public DefaultFunction(SerialAnalyserController parser){

        Collection prs = parser.getPRs();
        Iterator prIter = prs.iterator();
        while(prIter.hasNext()){
            ProcessingResource pr = (ProcessingResource) prIter.next();
            if (AbstractGazetteer.class.isAssignableFrom(pr.getClass())) {
                listGaz.add((AbstractGazetteer) pr);
            }

        }
        mongoDatastore = MongoDB.instance().getDatabase();

        Query<GrammarVariableEntity> q = mongoDatastore.createQuery(GrammarVariableEntity.class);
        for (GrammarVariableEntity var:q){
            String type = var.getType();
            if(type==null||type.equals(""))
                System.err.println(var.getName()+" null type!");
            if (type.contains(".")) {
                type = type.split("\\.")[0];
            }

            valType.put(var.getName(),type);

            for (String func:var.getDefaultFunction()){
                String [] splits = func.split("\\.");
                if(splits.length!=2)
                    continue;
                Map<String,String> assighVal = assignFunc.get(splits[0]);
                if(assighVal==null){
                    assighVal = new HashMap<>();
                    assignFunc.put(splits[0],assighVal);
                }
                assighVal.put(var.getName(),splits[1]);
            }
        }
    }

    public FeatureMap findGaz(String type, String slotValue){
        Set<Lookup> set = new HashSet<>();
        for (AbstractGazetteer gaz:listGaz){
            Set<Lookup> lookupset = gaz.lookup(slotValue);
            if(lookupset!=null)
                set.addAll(gaz.lookup(slotValue));
        }
        FeatureMap features = Factory.newFeatureMap();

        for (Lookup lookup:set){
            if(lookup.annotationType.equals(type)){
                features.putAll(lookup.features);
            }
        }
        return features;
    }


    public FeatureMap assignRelatedVal(FeatureMap features){

        FeatureMap featuresAdd = Factory.newFeatureMap();

        for (Object key:features.keySet()){
            FeatureMap slotVal = (FeatureMap)features.get(key);
            Map<String,String> assignVal = assignFunc.get(key);
            if(assignVal!=null && !assignVal.isEmpty()){
                for (String val:assignVal.keySet()){
                    String evalParam = (String) slotVal.get(assignVal.get(val));
                    String evalType = valType.get(val);

                    if(evalParam!=null && !evalParam.equals("")
                            &&evalType!=null&&!evalType.equals("")){
                        FeatureMap ret = findGaz(evalType,evalParam);
                        if(ret!=null&&!ret.isEmpty()){
                            featuresAdd.put(val,ret);
                        }
                    }
                }
            }
        }
        return featuresAdd;
    }
}
